package com.cts.rt.service.impl;

import java.util.List;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.cts.rt.dao.EmployeeDao;
import com.cts.rt.model.Employee;
import com.cts.rt.service.EmployeeManager;
import com.cts.rt.service.EmployeeService;
import com.cts.rt.service.UserExistsException;

/**
 * Implementation of UserManager interface.
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
@SuppressWarnings("deprecation")
@Service("employeeManager")
@WebService(serviceName = "EmployeeService", endpointInterface = "com.cts.rt.service.EmployeeService")
public class EmployeeManagerImpl extends GenericManagerImpl<Employee, Long>
		implements EmployeeManager, EmployeeService {

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private EmployeeDao employeeDao;

	@Autowired(required = false)
	private SaltSource saltSource;

	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	public void setEmployeeDao(EmployeeDao employeeDao) {
		this.dao = employeeDao;
		this.employeeDao = employeeDao;
	}

	/**
	 * {@inheritDoc}
	 */
	public Employee getEmployee(String employeeId) {
		return employeeDao.get(new Long(employeeId));
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Employee> getEmployees() {
		return employeeDao.getAllDistinct();
	}

	/**
	 * {@inheritDoc}
	 */
	public Employee saveEmployee(Employee employee) throws UserExistsException {

		if (employee.getId() == null) {

		}

		// Get and prepare password management-related artifacts
		boolean passwordChanged = false;
		if (passwordEncoder != null) {
			// Check whether we have to encrypt (or re-encrypt) the password
			if (employee.getId() == null) {
				// New user, always encrypt
				passwordChanged = true;
			} else {
				// Existing user, check password in DB
				String currentPassword = employeeDao
						.getEmployeePassword(employee.getId());
				if (currentPassword == null) {
					passwordChanged = true;
				} else {
					if (!currentPassword.equals(employee.getPassword())) {
						passwordChanged = true;
					}
				}
			}

			// If password was changed (or new user), encrypt it
			if (passwordChanged) {
				if (saltSource == null) {
					// backwards compatibility
					employee.setPassword(passwordEncoder.encodePassword(
							employee.getPassword(), null));
					log.warn("SaltSource not set, encrypting password w/o salt");
				} else {
					employee.setPassword(passwordEncoder.encodePassword(
							employee.getPassword(),
							saltSource.getSalt(employee)));
				}
			}
		} else {
			log.warn("PasswordEncoder not set, skipping password encryption...");
		}

		try {
			return employeeDao.saveEmployee(employee);
		} catch (Exception e) {
			e.printStackTrace();
			log.warn(e.getMessage());
			throw new UserExistsException("User '" + employee.getUsername()
					+ "' already exists!");
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeEmployee(Employee employee) {
		log.debug("removing user: " + employee);
		employeeDao.remove(employee);
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeEmployee(String employeeId) {
		log.debug("removing user: " + employeeId);
		employeeDao.remove(new Long(employeeId));
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @param username
	 *            the login name of the human
	 * @return User the populated user object
	 * @throws UsernameNotFoundException
	 *             thrown when username not found
	 */
	public Employee getUserByUsername(String username)
			throws UsernameNotFoundException {
		return (Employee) employeeDao.loadUserByUsername(username);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Employee> search(String searchTerm) {
		return super.search(searchTerm, Employee.class);
	}

}
